﻿/* Open source distributed without warranties of any kind. */

namespace Transcriber.Api
{
    #region Using
    using System;
    #endregion

    /// <summary>
    /// Base class for objects that implement <see cref="IDisposable"/>
    /// </summary>
    /// <remarks>
    /// The design of this class is based on a common pattern for
    /// <see cref="IDisposable"/> objects used in many Microsoft
    /// class libraries, turned into a re-usable polymorphic base
    /// class.
    /// </remarks>
    public abstract class Disposable : IDisposable
    {
        private bool mDisposed;

        /// <summary>
        /// Releases unmanaged resources and performs other cleanup operations before the
        /// <see cref="TranscriberPlugin"/> is reclaimed by garbage collection.
        /// </summary>
        ~Disposable()
        {
            this.Dispose(false);
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing,
        /// releasing, or resetting unmanaged resources.
        /// </summary>
        /// <remarks>
        /// Note that this method is deliberately neither abstract nor
        /// virtual. This base class provides the logic for implementing
        /// <see cref="IDisposable"/> in a manner that safely and efficiently
        /// interoperates with the garbage collector and guards against
        /// resource leaks and double deallocation leaks that can occur
        /// for naive implementations of <see cref="IDisposable.Dispose()"/>.
        /// Both <see cref="Finalize()"/> and <see cref="Dispose()"/> share
        /// a common private helper method which, in turns, relies on
        /// three virtual methods, <see cref="Terminate()"/>,
        /// <see cref="DisposeManaged()"/> and <see cref="DisposeUnmanaged()"/>.
        /// <seealso cref="Terminate()"/>
        /// <seealso cref="DisposeManaged()"/>
        /// <seealso cref="DisposeUnmanaged()"/>
        /// </remarks>
        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Terminates this instance.
        /// </summary>
        /// <remarks>
        /// Override this method to terminate worker threads,
        /// close communication end points or clean up any
        /// other dynamic state for your derived class. Do not
        /// dispose of any resources here, that is the purpose
        /// of <see cref="DisposeManaged()"/> and
        /// <see cref="DisposeUnmanaged()"/>.
        /// <seealso cref="DisposeManaged()"/>
        /// <seealso cref="DisposeUnmanaged()"/>
        /// </remarks>
        protected virtual void Terminate()
        {
        }

        /// <summary>
        /// Disposes of the managed resources owned by this instance.
        /// </summary>
        /// <remarks>
        /// Call the "close," "dispose" or similar methods of all
        /// managed resources owned by your derived class. Managed
        /// resources are instances of classes that are, themselves,
        /// managed by the garbage collector. Do not dispose of any
        /// unmanaged resources here as that is is the purpose of
        /// <see cref="DisposeUnmanaged"/> and keeping these methods
        /// distinct is an essential feature of the design of this
        /// class for correct, safe interaction with the garbage
        /// collector.
        /// <seealso cref="Terminate()"/>
        /// <seealso cref="DisposeUnmanaged()"/>
        /// </remarks>
        protected virtual void DisposeManaged()
        {
        }

        /// <summary>
        /// Disposes of the unmanaged resources owned by this instance.
        /// </summary>
        /// <remarks>
        /// Dispose of all unmanaged resources here. Unmanaged resources
        /// are allocated and freed using API's that bypass the garbage
        /// collector. Do dispose of any managed resources here as that
        /// is the purpose of <see cref="DisposeManaged()"/> and keeping
        /// these methods distinct is an essential feature of the design
        /// of this class for correct, safe interaction with the
        /// garbage collector.
        /// <seealso cref="Terminate()"/>
        /// <seealso cref="DisposeManaged()"/>
        /// </remarks>
        protected virtual void DisposeUnmanaged()
        {
        }

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing">
        /// <c>true</c> to release both managed and unmanaged resources;
        /// <c>false</c> to release only unmanaged resources.
        /// </param>
        private void Dispose(bool disposing)
        {
            if (!this.mDisposed)
            {
                this.Terminate();

                if (disposing)
                {
                    this.DisposeManaged();
                }

                this.DisposeUnmanaged();
                this.mDisposed = true;
            }
        }
    }
}
